/**
 * Class: Transition
 *
 * Purpose: 
 *
 * Created: Mar 3, 2010 @ 5:53:32 PM
 * @author Ken
 */
package org.openfantasia.util.math.transform;

import org.openfantasia.util.math.DPoint3;
import org.openfantasia.util.math.PMath;

public class Transition {

	// **************************************************************************

	public static class Linear extends Transform<Double> {

		protected double startValue = 0d;

		protected double endValue = 1d;


		public Linear() {
		}


		public Linear(double startValue, double endValue) {
			this.startValue = startValue;
			this.endValue = endValue;
		}


		public Double transform(Double value) {
			return PMath.lerp(startValue, endValue, value);
		}


		public double getStartValue() {
			return startValue;
		}


		public void setStartValue(double startValue) {
			this.startValue = startValue;
		}


		public double getEndValue() {
			return endValue;
		}


		public void setEndValue(double endValue) {
			this.endValue = endValue;
		}
	}

	// **************************************************************************

	public static class Map1D extends Linear {

		protected double startMap = 0d;

		protected double endMap = 2d;


		public Map1D() {
		}


		public Map1D(double startValue, double endValue, double startMap, double endMap) {
			super(startValue, endValue);
			this.startMap = startMap;
			this.endMap = endMap;
		}


		public Double transform(Double value) {
			return PMath.map(value, startValue, endValue, startMap, endMap);
		}


		public double getStartMap() {
			return startMap;
		}


		public void setStartMap(double startMap) {
			this.startMap = startMap;
		}


		public double getEndMap() {
			return endMap;
		}


		public void setEndMap(double endMap) {
			this.endMap = endMap;
		}
	}

	// **************************************************************************

	public static class Linear3D extends Transform<DPoint3> {

		protected DPoint3 startPoint;

		protected DPoint3 endPoint;


		public Linear3D() {
		}


		public Linear3D(DPoint3 startPoint, DPoint3 endPoint) {
			this.startPoint = startPoint;
			this.endPoint = endPoint;
		}


		public DPoint3 transform(DPoint3 value) {
			double px = PMath.lerp(startPoint.getX(), endPoint.getX(), value.getX());
			double py = PMath.lerp(startPoint.getY(), endPoint.getY(), value.getY());
			double pz = PMath.lerp(startPoint.getZ(), endPoint.getZ(), value.getZ());

			return new DPoint3(px, py, pz);
		}


		public DPoint3 getStartPoint() {
			return startPoint;
		}


		public void setStartPoint(DPoint3 startPoint) {
			this.startPoint = startPoint;
		}


		public DPoint3 getEndPoint() {
			return endPoint;
		}


		public void setEndPoint(DPoint3 endPoint) {
			this.endPoint = endPoint;
		}
	}

	public static class Curve3D extends Linear3D {

		protected DPoint3 deviation;


		public Curve3D() {
		}


		public Curve3D(DPoint3 startPoint, DPoint3 endPoint, DPoint3 deviation) {
			super(startPoint, endPoint);
			this.deviation = deviation;
		}


		public DPoint3 transform(DPoint3 value) {
			double vx = value.getX();
			double vy = value.getY();
			double vz = value.getZ();

			double px = PMath.lerp(startPoint.getX(), endPoint.getX(), vx) + deviation.getX() * PMath.sin(PMath.PI * vx);
			double py = PMath.lerp(startPoint.getY(), endPoint.getY(), vy) + deviation.getY() * PMath.sin(PMath.PI * vy);
			double pz = PMath.lerp(startPoint.getZ(), endPoint.getZ(), vz) + deviation.getZ() * PMath.sin(PMath.PI * vz);

			return new DPoint3(px, py, pz);
		}
	}

	// **************************************************************************

	public static class Map3D extends Linear3D {

		protected DPoint3 startMap;

		protected DPoint3 endMap;


		public Map3D() {
		}


		public Map3D(DPoint3 startPoint, DPoint3 endPoint, DPoint3 startMap, DPoint3 endMap) {
			super(startPoint, endPoint);
			this.startMap = startMap;
			this.endMap = endMap;
		}


		public DPoint3 transform(DPoint3 value) {
			double px = PMath.map(value.getX(), startPoint.getX(), endPoint.getX(), startMap.getX(), endMap.getX());
			double py = PMath.map(value.getY(), startPoint.getY(), endPoint.getY(), startMap.getY(), endMap.getY());
			double pz = PMath.map(value.getZ(), startPoint.getZ(), endPoint.getZ(), startMap.getZ(), endMap.getZ());

			return new DPoint3(px, py, pz);
		}


		public DPoint3 getStartMap() {
			return startMap;
		}


		public void setStartMap(DPoint3 startMap) {
			this.startMap = startMap;
		}


		public DPoint3 getEndMap() {
			return endMap;
		}


		public void setEndMap(DPoint3 endMap) {
			this.endMap = endMap;
		}
	}
}
